--- The non-recursive form of several types,as used in @GenMeta@
--- This corresponds closely to the interfaces in @frege.runtime.Meta@
module frege.compiler.types.External where 

import  frege.compiler.types.QNames

{-- 
    Encode 'Tau' types and 'Kind's.

    The @kind@ field encodes what it is:
    0) 'TApp', uses fields @suba@ and @subb@ to point to affected 'Tau's
    1) unused
    2) 'TCon', uses field @tcon@
    3) 'TVar', uses field @tvar@ for the name and @suba@ for an index that encode a 'Kind'
    8) 'KApp', uses fields @suba@ and @subb@ to point to affected 'Kind's
    9) 'KType'
    10) 'KVar' (must not happen)
    11) 'KGen' uses field @suba@ to point to a single  'Tau'
    12) 'KGen' uses field @suba@ to point to the first 'Tau', @subb@ to point to the second 'Tau'
    13) 'KGen' @suba@ is an index to the first 'Tau', @subb@ points to the next 'KGen' node.
        This is so that @extends T1 & T2 & ... & Tn@ can be encoded and yet most generic kinds
        can get away with just 1 node (11 for @extends T1@ and 12 for @extends T1 & T2@). For
        3 types we need 1 node 13 and 1 node 12, and so on. Example:
    
    > data Foo; data Bar; data Baz; data Bum;
    > data Z (a ≤ Foo, Bar, Baz, Bum)
    could be encoded like so:
    > Index     Node (simplified for qualified names)
    >   0       TauA{kind=2, tcon="Foo"}
    >   1       TauA{kind=2, tcon="Bar"}
    >   2       TauA{kind=2, tcon="Baz"}
    >   3       TauA{kind=2, tcon="Bum"}
    >   4       TauA{kind=2, tcon="Z"}
    >   5       TauA{kind=3, tvar="a", suba=6}
    >   6       TauA{kind=13, suba=0, subb=7}
    >   7       TauA{kind=13, suba=1, subb=8}
    >   8       TauA{kind=12, suba=2, subb=3}    
-}
data TauA = TauA {!kind::Int, !tcon::Maybe QName, !suba::Int, !subb::Int, !tvar::String}
derive ArrayElement TauA
derive Eq  TauA
derive Ord TauA


data RhoA = RhoA {!rhofun::Bool, !cont::[ContextA], !sigma::Int, !rhotau::Int}
derive ArrayElement RhoA
derive Eq  RhoA
derive Ord RhoA


data ContextA = CtxA {!clas::QName, !tau::Int}
derive Eq  ContextA
derive Ord ContextA


data SigmaA = SigmaA {!bound::[String], !kinds::[Int], !rho::Int}
derive ArrayElement SigmaA
derive Eq  SigmaA
derive Ord SigmaA


data ExprA = !ExprA {xkind::Int, name::Maybe QName, lkind::Int, varval::Maybe String,
                    alts :: [Int], subx1 :: Int, subx2 :: Int, subx3 :: Int}
derive ArrayElement ExprA
derive Eq  ExprA
derive Ord ExprA


--- default "serialized" expression
defEA = ExprA {xkind = 7, name = Nothing, lkind = 0, varval = Nothing, alts = [],
                subx1 = 0, subx2 = 0, subx3 = 0}


